home *** CD-ROM | disk | FTP | other *** search
- /*
- CPULoad
- (C) Thomas Radtke 1994
-
- main: Process, Initialisierungen und buisy loop
- druck: Task, Graphische Ausgabe
- IdleIrq: IRQ server, Auswertung des buisy loop
-
- Um double-Rechnungen zu vermeiden werden ULONG's in beide Richtungen
- geshiftet. Bei hohen Rechenleistungen kann dies ggf. zu Überläufen
- führen. Abhilfe bringt eine Verringerung des 'aktuell'-Wertes
- ('aktuell>>n') um ein geeignetes n.
-
- Das Abbruchsignal ist CTRL-D. Niemals CTRL-C verwenden, wenn der
- Compiler dieses Signal als generellen Abbruch benutzt.
-
- Basiert auf Idle LED von Lindsay Meek.
-
- read the README !
-
-
- Version 1.1 modifications (Mar-26-95) by Jean-Guy Speton:
-
- - Fixed source to compile with DICE 3.0, which mainly involved the
- insertion of __geta4 for IdleCPU() and druck().
- - Added prototype #include's, removed local protypes of system calls,
- which made my system crash. :-(
- - Changed comments to C++ style, which I prefer, and deleted some
- German comments which I didn't understand. Apologies to Thomas.
- - cast'ed system calls to get rid of compiler warnings.
- - Replaced explicit priority changes with calls to SetTaskPri().
- - Replaced explicit signal changes and queries with SetSignal().
- - Window now opened with OpenWindowTags rather than OpenWindow().
- - Changed expensive GIMMEZEROZERO window to non-GZZ window.
- - Changed CTRL-D handling to CTRL-C, so you can 'break' it from a CLI.
- - Added hash lines at 1/4, 1/2 and 3/4 the way down the window.
- Set the colour yourself if you don't like mine by changing HASH_PEN.
- - Removed sizing gadget and added zip gadget, the way I like it.
- (I thought the sizing gadget made the window look ugly.)
- - Added command line options LEFT, TOP, WIDTH and HEIGHT to specify
- initial location and size of window.
- - Added UPDATE command line option, which sets how often the graph is
- updated. ie. Update every UPDATE seconds. Default is 1.
- */
-
- const char *dummy="$VER: CPULoad 1.1";
-
- #include <intuition/intuitionbase.h>
- #include <exec/nodes.h>
- #include <exec/tasks.h>
- #include <exec/interrupts.h>
- #include <hardware/intbits.h>
- #include <libraries/dos.h>
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <signal.h>
-
- #include <clib/alib_protos.h>
- #include <clib/exec_protos.h>
- #include <clib/intuition_protos.h>
- #include <clib/dos_protos.h>
-
- __geta4 void druck(void);
- __geta4 int IdleCPU(void);
-
- #define HASH_PEN 0 // Pen used for hash lines.
-
- // Template string and variables used for command line arguments.
-
- #define TEMPLATE "L=LEFT/N,T=TOP/N,W=WIDTH/N,H=HEIGHT/N,U=UPDATE/N"
- LONG WIN_LEFT, WIN_TOP, WIN_WIDTH, WIN_HEIGHT, UPDATE;
-
- BOOL must_quit = FALSE;
-
- // Stacksize für den Grafik-Task (1000 < STACK_SIZE < 10000)
-
- #define STACK_SIZE 4000L
-
- struct Task *task = NULL;
- char *taskname = "CPULoad";
-
- struct timerequest *tr;
- struct MsgPort *tport;
- struct Message *msg;
- struct Window *CustWindow;
- struct IntuitionBase *IntuitionBase;
- struct GfxBase *GfxBase;
-
- #define rp CustWindow->RPort
- #define bl CustWindow->BorderLeft
- #define bt CustWindow->BorderTop
- #define br CustWindow->BorderRight
- #define bb CustWindow->BorderBottom
- #define ww CustWindow->Width
- #define wh CustWindow->Height
-
- unsigned int maximum,aktuell;
-
- struct Task *met2;
-
- #define UTILITY_NAME "IdleCPU"
-
- // Various counters used to detect the idle state in the vblank.
-
- static ULONG idle_vbi_cnt_limit[3];
-
- struct timerequest *create_timer(ULONG unit)
- {
- LONG error;
- struct MsgPort *timerport;
- struct timerequest *timermsg;
-
- if ((timerport = (struct MsgPort *)CreatePort(0,0)) == NULL)
- exit(1);
- if ((timermsg = (struct timerequest *)CreateExtIO(timerport,sizeof(struct timerequest))) == NULL)
- exit(1);
- if ((error = OpenDevice(TIMERNAME,unit,(struct IORequest *)timermsg,0)) != 0)
- exit(1);
- return(timermsg);
- }
-
- __geta4 int IdleCPU() {
- idle_vbi_cnt_limit[0] = 1;
- aktuell = idle_vbi_cnt_limit[1];
- idle_vbi_cnt_limit[1] = 0;
- return 0;
- }
-
- __geta4 void druck() {
- struct IntuiMessage *message;
- struct timeval updateval;
- LONG n;
- unsigned int sum;
- LONG height,width,left,right,top,bottom;
- ULONG int_pix_per_load;
- int whitepen,blackpen;
- struct Screen *PubScreen;
- short pen,minpen,maxpen;
- unsigned short RGB;
- int class;
-
- // init timer
-
- tr = create_timer(UNIT_MICROHZ);
-
- updateval.tv_secs=0;
- updateval.tv_micro=100000; /* 1/10 secs */
-
- IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0);
- GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0);
-
- PubScreen = LockPubScreen(NULL);
-
- WORD zoom_words[4] = {WIN_LEFT, WIN_TOP, WIN_WIDTH, PubScreen->WBorTop + PubScreen->Font->ta_YSize + 1};
-
- CustWindow = OpenWindowTags(NULL,
- WA_Left, WIN_LEFT,
- WA_Top, WIN_TOP,
- WA_Width, WIN_WIDTH,
- WA_Height, WIN_HEIGHT,
- WA_MinWidth,50,
- WA_MinHeight,25,
- WA_IDCMP, CLOSEWINDOW | NEWSIZE | CHANGEWINDOW,
- WA_Flags, ACTIVATE | SMART_REFRESH | WINDOWCLOSE | WINDOWDRAG | WINDOWDEPTH,
- WA_Title, "CPULoad",
- WA_PubScreen,PubScreen,
- WA_Zoom, zoom_words,
- NULL);
-
- UnlockPubScreen(NULL,PubScreen);
- CustWindow->MinHeight = bt;
-
- whitepen = 1;
- blackpen = 0;
- maxpen = 0x000;
- minpen = 0xfff;
-
- for (n = 0; n < (1 << PubScreen->BitMap.Depth); n++) {
- RGB = GetRGB4(PubScreen->ViewPort.ColorMap,n);
-
- pen = (RGB & 0x00f) + ((RGB & 0x0f0) >> 4) + ((RGB & 0xf00) >> 8);
-
- if (pen < minpen) {
- minpen = pen;
- blackpen = n;
- }
- if (pen > maxpen) {
- maxpen = pen;
- whitepen = n;
- }
- }
-
- height = wh - bt - bb;
- width = ww - br - bl;
- left = bl;
- right = left + width - 1;
- top = bt;
- bottom = bt + height - 1;
-
- SetAPen(rp,whitepen);
- RectFill(rp,left,top,right,bottom);
-
- SetAPen(rp, HASH_PEN);
- Move(rp, left, top + height/4);
- Draw(rp, right, top + height/4);
- Move(rp, left, top + height/2);
- Draw(rp, right, top + height/2);
- Move(rp, left, top + 3*height/4);
- Draw(rp, right, top + 3*height/4);
-
- while (1) {
-
- if (must_quit) {
- Signal(met2, SIGBREAKF_CTRL_D);
- Wait(0L);
- }
-
- sum = 0;
- for (n = 0; n < 10; n++) {
- sum += aktuell;
-
- updateval.tv_micro = 100000 * UPDATE;
-
- tr->tr_node.io_Command = TR_ADDREQUEST;
- tr->tr_time = updateval;
- DoIO((struct IORequest *)tr);
- }
-
- sum /= 10; // Average over 10 samples.
-
- if (wh > bt) {
- height = wh - bt - bb;
- width = ww - br - bl;
- left = bl;
- right = left + width - 1;
- top = bt;
- bottom = bt + height - 1;
-
- int_pix_per_load = (height<<16)/maximum;
-
- ScrollRaster(rp,1,0,left,top,right,bottom);
-
- Move(rp,right,bottom);
-
- SetAPen(rp,blackpen);
- Draw(rp, right, top + ((sum * int_pix_per_load) >> 16));
- if (rp->cp_y > top) {
- SetAPen(rp,whitepen);
- Draw(rp,right,top);
- }
-
- // Fill in the displaced hash-line points.
-
- SetAPen(rp, HASH_PEN);
- Move(rp, right, top + height/4);
- Draw(rp, right, top + height/4);
- Move(rp, right, top + height/2);
- Draw(rp, right, top + height/2);
- Move(rp, right, top + 3*height/4);
- Draw(rp, right, top + 3*height/4);
- }
-
- while (message = (struct IntuiMessage *)GetMsg(CustWindow->UserPort)) {
- if ((class = message->Class) == CLOSEWINDOW) {
- ReplyMsg((struct Msg *)message);
- Signal(met2, SIGBREAKF_CTRL_C);
- Signal(met2, SIGBREAKF_CTRL_D);
- SetTaskPri(met2, 1L); // So it doesn't have to wait if CPU usage is 100%.
- Wait(0L); // Parent process will DeleteTask() us.
- }
- else if (class == NEWSIZE) {
- ReplyMsg((struct Msg *)message);
- if (wh > bt) {
- SetAPen(rp,whitepen);
- RectFill(rp,left,top,right,bottom);
- SetAPen(rp, HASH_PEN);
- Move(rp, left, top + height/4);
- Draw(rp, right, top + height/4);
- Move(rp, left, top + height/2);
- Draw(rp, right, top + height/2);
- Move(rp, left, top + 3*height/4);
- Draw(rp, right, top + 3*height/4);
- }
- }
- else if (class == CHANGEWINDOW)
- ReplyMsg((struct Msg *)message);
- }
- }
- }
-
- // Run this as a process. It aborts when it detects a CTRL_C signal.
-
- main()
- {
- struct Task *met;
- struct Interrupt mei;
- WORD oldpri;
- char *oldname;
- struct RdArgs *ra;
- LONG args[5] = { 0L, 0L, 0L, 0L, 0L };
-
- // Switch off CTRL_C handling, we'll handle it ourselves.
-
- signal(SIGINT,SIG_IGN);
-
- // Read command-line arguments.
-
- if (ra = ReadArgs(TEMPLATE, args, NULL)) {
- WIN_LEFT = (args[0] ? *(LONG *)args[0] : 0);
- WIN_TOP = (args[1] ? *(LONG *)args[1] : 0);
- WIN_WIDTH = (args[2] ? *(LONG *)args[2] : 130);
- WIN_HEIGHT = (args[3] ? *(LONG *)args[3] : 100);
- UPDATE = (args[4] ? *(LONG *)args[4] : 1);
- if (UPDATE < 1) // A value of 0 would be unacceptable.
- UPDATE = 1;
- FreeArgs(ra);
- }
- else
- exit(1);
-
- // Remove CPULoad if already present.
-
- if (met = FindTask(UTILITY_NAME)) {
- Signal(met,SIGBREAKF_CTRL_C);
- exit(0);
- }
-
- // Setup for IRQ
-
- mei.is_Node.ln_Type = NT_INTERRUPT;
- mei.is_Node.ln_Pri = -127;
- mei.is_Node.ln_Name = UTILITY_NAME;
- mei.is_Data = (APTR)0; // idle_vbi_cnt_limit;
- mei.is_Code = (void *)IdleCPU;
-
- AddIntServer(INTB_VERTB, &mei); // Install IRQ server.
-
- met=FindTask(NULL);
- oldname=met->tc_Node.ln_Name; // Save old name.
- met->tc_Node.ln_Name=UTILITY_NAME;
-
- oldpri = SetTaskPri(met, 40);
-
- met2 = met; // Pointer for druck().
-
- // Reset counters.
-
- idle_vbi_cnt_limit[0]=0;
- idle_vbi_cnt_limit[1]=0;
- idle_vbi_cnt_limit[2]=0;
-
- // Wait for next vbi, nicht ganz astrein.
-
- Forbid();
-
- while(idle_vbi_cnt_limit[0] == 0) ;
-
- // Count # of increments in one frame (for calibration).
-
- idle_vbi_cnt_limit[2] = 0;
- idle_vbi_cnt_limit[0] = 0;
- while (idle_vbi_cnt_limit[0] == 0)
- idle_vbi_cnt_limit[2]++;
-
- Permit();
-
- // druck() braucht maximum
-
- maximum = idle_vbi_cnt_limit[2];
-
- // printf("%d\n",maximum); fflush(stdout);
-
- task = CreateTask(taskname,30,druck,STACK_SIZE);
-
- SetTaskPri(met, -127);
-
- // Busy loop for eating up idle CPU cycles.
-
- SetSignal(0L, SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D); // Ignore queued CTRL_C and CTRL_D.
-
- while((met->tc_SigRecvd & SIGBREAKF_CTRL_C) == 0) // Abort on CTRL_C
- idle_vbi_cnt_limit[1]++; // Increment idle counter
-
- // We cannot remove the child if it's waiting for timer IO
- // so we wait for it to send us a CTRL_D, which means it
- // is ready to be killed.
-
- must_quit = TRUE; // Let the task know it must quit.
- Wait(SIGBREAKF_CTRL_D);
-
- RemIntServer(INTB_VERTB,&mei); // Remove IRQ server.
- SetTaskPri(met, oldpri);
- met->tc_Node.ln_Name=oldname; // Change name back.
-
- if (tr) {
- CloseDevice((struct IORequest *)tr);
- DeleteExtIO((struct IORequest *)tr);
- }
-
- if (CustWindow)
- CloseWindow(CustWindow);
-
- DeleteTask(task);
-
- if (IntuitionBase)
- CloseLibrary((struct Library *)IntuitionBase);
- if (GfxBase)
- CloseLibrary(GfxBase);
-
- exit(0);
- }
-